package com.alangyun.remind.service.impl;

import java.io.Serializable;
import java.util.*;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alangyun.remind.enums.EducationType;
import com.alangyun.remind.utils.MyDateUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.alangyun.remind.BaseActor;
import com.alangyun.remind.error.MindException;
import com.alangyun.remind.repository.StoreEngine;
import com.alangyun.remind.repository.algorithm.Education;
import com.alangyun.remind.repository.cache.TalentCache;
import com.alangyun.remind.repository.data.NameTerm;
import com.alangyun.remind.repository.data.TalentCaution;
import com.alangyun.remind.repository.data.TalentDataset;
import com.alangyun.remind.service.ITalentService;
import com.alangyun.remind.utils.Utility;
import com.alangyun.remind.vo.talent.AbilityView;
import com.alangyun.remind.vo.talent.AgeRatioView;
import com.alangyun.remind.vo.talent.AgeYearsView;
import com.alangyun.remind.vo.talent.SudokuCellView;
import com.alangyun.remind.vo.talent.SudokuView;
import com.alangyun.remind.vo.talent.TrendView;
import com.alangyun.remind.vo.FilterParam;
import com.alangyun.remind.vo.talent.AbilityTeamView;
import com.alangyun.remind.vo.talent.AbilityUserView;

@Service
public class TalentService extends BaseActor implements ITalentService {
	@Value("${trendForecast.years.professional}")
	Integer professionalNumTrendForecastYears;

	@Value("${trendForecast.years.professionalTitle}")
	Integer professionalTitleNumTrendForecastYears;

	@Value("${trendForecast.years.technology}")
	Integer technologyNumTrendForecastYears;

	@Value("${trendForecast.maxProfessionAge.male}")
	Integer maleMaxProfessionAge;

	@Value("${trendForecast.maxProfessionAge.female}")
	Integer femaleMaxProfessionAge;

	@Value("${trendForecast.minRecentYearsPerformance}")
	Double minRecentYearsPerformance;



	private static String[] AgeLevel = new String[] {
			"35岁以下",
			"30岁以下",
			"30岁(含)~35岁",
			"35岁(含)~50岁以下",
			"30岁(含)~39岁",
			"40岁(含)~44岁",
			"45岁(含)~50岁",
			"50岁(含)以上",
			"50岁(含)~55岁",
			"55岁(含)以上"
	};
	
	private void validateDataset() {
			if (!TalentCache.my().isLoaded()) {
				try {
				TalentDataset data = StoreEngine.openDataset(TalentDataset.class,
						new Class<?>[] { TalentCaution.class, NameTerm.class });
				TalentCache.my().addDataset(data);
				} catch (Exception ex) {
					throw new MindException("加载专业技能预警数据失败，请确认是否已上传预警数据", ex);
				}
			}

	}

	@Override
	public FilterParam categories() {

		validateDataset();

		TalentDataset db= TalentCache.my().get();

		FilterParam ret = new FilterParam();
		ret.setJobs(db.getJobs());
		ret.setProfs(db.getProfs());
		ret.setTeams(db.getTeams());
		
		return ret;
	}

	@Override
	public AbilityView listBySize(int size) {
		validateDataset();

		TalentDataset data = TalentCache.my().get();
		if (data == null)
			return null;

		if (size <= 0 || size > 20)
			size = 15;

		AbilityView ret = AbilityView.create();
		// 处理部门
		if (data.getTeams().size() > 0) {
			int count = 0;

			for (NameTerm unit : data.getTeams()) {
				if (unit.getNodes() != null && unit.getNodes().size() > 0) {
					for (NameTerm depart : unit.getNodes()) {
						// 如果大于所需数，则退出
						if (count++ > size)
							break;

						AbilityTeamView view = new AbilityTeamView();
						view.setId(depart.getId());
						view.setName(depart.getText());
						view.setUnit(unit.getText());
						ret.getTeams().add(view);
					}
				}
				// 如果大于所需数，则退出
				if (count > size)
					break;
			}
		}
		// 处理人员并统计
		if (ret.getTeams().size() > 0 && data.getDatas() != null && data.getDatas().size() > 0) {
			for (AbilityTeamView view : ret.getTeams()) {
				double ybnl = 0.0;// 一般能力
				double tysrl = 0.0;// 通用胜任力
				double zyzsjn = 0.0;// 专业知识和技能
				double zhzyhnl = 0.0;// 综合专业能力水平
				int count = 0;
				for (TalentCaution caution : data.getDatas()) {
					if (caution.getDepart().intValue() == view.getId().intValue()) {
						ybnl += caution.getYbnl();
						tysrl += caution.getTysrl();
						zyzsjn += caution.getZyzsjn();
						zhzyhnl += caution.getZhzyhnl();

						AbilityUserView user = new AbilityUserView();
						user.setId(count++);
						user.setNo(caution.getId());
						user.setName(caution.getName());
						user.setUnit(view.getUnit());
						user.setDepart(view.getName());
						user.setClassOrGroup(TalentCache.my().getTeamName(caution.getClassOrGroup()));
						user.setJob(caution.getJob01Name());

						user.setYbnl(caution.getYbnl());
						user.setTysrl(caution.getTysrl());
						user.setZyzsjn(caution.getZyzsjn());
						user.setZhzyhnl(caution.getZhzyhnl());

						user.setCzsjzzy(caution.getCzsjzzy());
						user.setCzsjzw(caution.getCzsjzw());
						user.setScgwg3n(caution.getScgwg3n());
						user.setYxgwg3n(caution.getYxgwg3n());
						user.setRyzhly(caution.getRyzhly());
						user.setRyzyly(caution.getRyzyly());
						user.setRyjtlry(caution.getRyjtlry());
						user.setRyzgry(caution.getRyzgry());
						user.setRctchxtn(caution.getRctchxtn());
						user.setRctchxtw(caution.getRctchxtw());
						ret.getUsers().add(user);
					}
				}
				// 求平均值
				count = count > 0 ? count : 1;
				view.setYbnl(ybnl / count);
				view.setTysrl(tysrl / count);
				view.setZyzsjn(zyzsjn / count);
				view.setZhzyhnl(zhzyhnl / count);
			}
		}

		return ret;
	}

//	@Override
//	public AbilityView listByDepart(Integer[] depart, Integer[] profs, Integer[] jobs) {
//
//		if (depart == null || depart.length == 0)
//			return null;
//
//		validateDataset();
//
//		TalentDataset data = TalentCache.my().get();
//		if (data == null)
//			return null;
//
//		AbilityView ret = AbilityView.create();
//
//		for (Integer d : depart) {
//			NameTerm nt = TalentCache.my().getTeam(d);
//			if (nt != null) {
//				AbilityTeamView team = new AbilityTeamView();
//				team.setId(nt.getId());
//				team.setName(nt.getName());
//				ret.getTeams().add(team);
//			}
//		}
//
//		// 处理人员并统计
//		if (ret.getTeams().size() > 0 && data.getDatas() != null && data.getDatas().size() > 0) {
//			for (AbilityTeamView view : ret.getTeams()) {
//				double ybnl = 0.0;// 一般能力
//				double tysrl = 0.0;// 通用胜任力
//				double zyzsjn = 0.0;// 专业知识和技能
//				double zhzyhnl = 0.0;// 综合专业能力水平
//				int count = 0;
//				for (TalentCaution caution : data.getDatas()) {
//					if (Utility.inArray(depart, caution.getDepart()) && Utility.inArray(profs, caution.getTechProf())
//							&& Utility.inArray(jobs, caution.getJob())) {
//						ybnl += caution.getYbnl();
//						tysrl += caution.getTysrl();
//						zyzsjn += caution.getZyzsjn();
//						zhzyhnl += caution.getZhzyhnl();
//
//						AbilityUserView user = new AbilityUserView();
//						user.setId(count++);
//						user.setNo(caution.getId());
//						user.setName(caution.getName());
//						user.setUnit(TalentCache.my().getTeamName(caution.getUnit()));
//						user.setDepart(view.getName());
//						user.setClassOrGroup(TalentCache.my().getTeamName(caution.getClassOrGroup()));
//						user.setJob(TalentCache.my().getTeamName(caution.getJob()));
//
//						user.setYbnl(caution.getYbnl());
//						user.setTysrl(caution.getTysrl());
//						user.setZyzsjn(caution.getZyzsjn());
//						user.setZhzyhnl(caution.getZhzyhnl());
//
//						ret.getUsers().add(user);
//					}
//				}
//				// 求平均值
//				count = count > 0 ? count : 1;
//				view.setYbnl(ybnl / count);
//				view.setTysrl(tysrl / count);
//				view.setZyzsjn(zyzsjn / count);
//				view.setZhzyhnl(zhzyhnl / count);
//			}
//		}
//
//		return ret;
//	}
	
	@Override
	public AbilityView listByDepart(Integer[] depart, Integer[] profs, Integer[] jobs) {

		validateDataset();

		TalentDataset data = TalentCache.my().get();
		if (data == null)
			return null;

		AbilityView ret = AbilityView.create();

		// 处理人员并统计
		if (data.getDatas() != null && data.getDatas().size() > 0) {
			Map<Integer, AbilityTeamView> termMap = new HashMap<>();
			int count = 0;
			for (TalentCaution caution : data.getDatas()) {
				if (Utility.inArray(depart, caution.getDepart()) && Utility.inArray(profs, caution.getTechLevel())
						&& Utility.inArray(jobs, caution.getJob01())) {

					AbilityUserView user = new AbilityUserView();
					user.setId(count++);
					user.setNo(caution.getId());
					user.setName(caution.getName());
					user.setUnit(TalentCache.my().getTeamName(caution.getUnit()));
					user.setDepart(TalentCache.my().getTeamName(caution.getDepart()));// view.getName());
					user.setClassOrGroup(TalentCache.my().getTeamName(caution.getClassOrGroup()));
					user.setJob(caution.getJob01Name());

					user.setYbnl(caution.getYbnl());
					user.setTysrl(caution.getTysrl());
					user.setZyzsjn(caution.getZyzsjn());
					user.setZhzyhnl(caution.getZhzyhnl());

					ret.getUsers().add(user);
					// 查看有无统计项并统计
					AbilityTeamView view = termMap.get(caution.getDepart());
					if (view == null) {
						view = new AbilityTeamView();
						view.setName(user.getDepart()==null?"未知项":user.getDepart());
						termMap.put(caution.getDepart(), view);
					}
					view.setYbnl(view.getYbnl() + caution.getYbnl());
					view.setTysrl(view.getTysrl() + caution.getTysrl());
					view.setZyzsjn(view.getZyzsjn() + caution.getZyzsjn());
					view.setZhzyhnl(view.getZhzyhnl() + caution.getZhzyhnl());
					view.incCount();
				}
			}
			// 求平均值
			if (termMap.size() > 0) {
				for (AbilityTeamView view : termMap.values()) {
					int viewCount = view.getCount();
					viewCount = viewCount > 0 ? viewCount : 1;
					view.setYbnl(view.getYbnl() / count);
					view.setTysrl(view.getTysrl() / count);
					view.setZyzsjn(view.getZyzsjn() / count);
					view.setZhzyhnl(view.getZhzyhnl() / count);
					
					ret.getTeams().add(view);
				}
			}
		}

		return ret;
	}

	@Override
	public AbilityView listByProf(Integer[] depart, Integer[] profs, Integer[] jobs) {

		validateDataset();

		TalentDataset data = TalentCache.my().get();
		if (data == null)
			return null;

		AbilityView ret = AbilityView.create();

		// 处理人员并统计
		if (data.getDatas() != null && data.getDatas().size() > 0) {
			Map<Integer, AbilityTeamView> termMap = new HashMap<>();
			int count = 0;
			for (TalentCaution caution : data.getDatas()) {
				if (Utility.inArray(depart, caution.getDepart()) && Utility.inArray(profs, caution.getTechLevel())
						&& Utility.inArray(jobs, caution.getJob01())) {

					AbilityUserView user = new AbilityUserView();
					user.setId(count++);
					user.setNo(caution.getId());
					user.setName(caution.getName());
					user.setUnit(TalentCache.my().getTeamName(caution.getUnit()));
					user.setDepart(TalentCache.my().getTeamName(caution.getDepart()));// view.getName());
					user.setClassOrGroup(TalentCache.my().getTeamName(caution.getClassOrGroup()));
					user.setJob(caution.getJob01Name());

					user.setYbnl(caution.getYbnl());
					user.setTysrl(caution.getTysrl());
					user.setZyzsjn(caution.getZyzsjn());
					user.setZhzyhnl(caution.getZhzyhnl());

					ret.getUsers().add(user);
					// 查看有无统计项并统计
					AbilityTeamView view = termMap.get(caution.getTechLevel());
					if (view == null) {
						view = new AbilityTeamView();
						String name = TalentCache.my().getTeamName(caution.getTechLevel());
						name= name==null||name.trim().length()==0?"未知项": name;
						view.setName(name);
						termMap.put(caution.getTechLevel(), view);
					}
					view.setYbnl(view.getYbnl() + caution.getYbnl());
					view.setTysrl(view.getTysrl() + caution.getTysrl());
					view.setZyzsjn(view.getZyzsjn() + caution.getZyzsjn());
					view.setZhzyhnl(view.getZhzyhnl() + caution.getZhzyhnl());
					view.incCount();
				}
			}
			// 求平均值
			if (termMap.size() > 0) {
				for (AbilityTeamView view : termMap.values()) {
					int viewCount = view.getCount();
					viewCount = viewCount > 0 ? viewCount : 1;
					view.setYbnl(view.getYbnl() / count);
					view.setTysrl(view.getTysrl() / count);
					view.setZyzsjn(view.getZyzsjn() / count);
					view.setZhzyhnl(view.getZhzyhnl() / count);
					
					ret.getTeams().add(view);
				}
			}
		}

		return ret;
	}

	@Override
	public AbilityView listByClass(Integer[] depart, Integer[] profs, Integer[] jobs) {

		validateDataset();

		TalentDataset data = TalentCache.my().get();
		if (data == null)
			return null;

		AbilityView ret = AbilityView.create();

		// 处理人员并统计
		if (data.getDatas() != null && data.getDatas().size() > 0) {
			Map<Integer, AbilityTeamView> termMap = new HashMap<>();
			int count = 0;
			for (TalentCaution caution : data.getDatas()) {
				if (Utility.inArray(depart, caution.getDepart()) && Utility.inArray(profs, caution.getTechLevel())
						&& Utility.inArray(jobs, caution.getJob01())) {

					AbilityUserView user = new AbilityUserView();
					user.setId(count++);
					user.setNo(caution.getId());
					user.setName(caution.getName());
					user.setUnit(TalentCache.my().getTeamName(caution.getUnit()));
					user.setDepart(TalentCache.my().getTeamName(caution.getDepart()));// view.getName());
					user.setClassOrGroup(TalentCache.my().getTeamName(caution.getClassOrGroup()));
					user.setJob(caution.getJob01Name());

					user.setYbnl(caution.getYbnl());
					user.setTysrl(caution.getTysrl());
					user.setZyzsjn(caution.getZyzsjn());
					user.setZhzyhnl(caution.getZhzyhnl());

					ret.getUsers().add(user);
					// 查看有无统计项并统计
					AbilityTeamView view = termMap.get(caution.getClassOrGroup());
					if (view == null) {
						view = new AbilityTeamView();
						String name=user.getClassOrGroup();
						name= name==null||name.trim().length()==0?"未知项": name;
						view.setName(name);
						termMap.put(caution.getClassOrGroup(), view);
					}
					view.setYbnl(view.getYbnl() + caution.getYbnl());
					view.setTysrl(view.getTysrl() + caution.getTysrl());
					view.setZyzsjn(view.getZyzsjn() + caution.getZyzsjn());
					view.setZhzyhnl(view.getZhzyhnl() + caution.getZhzyhnl());
					view.incCount();
				}
			}
			// 求平均值
			if (termMap.size() > 0) {
				for (AbilityTeamView view : termMap.values()) {
					int viewCount = view.getCount();
					viewCount = viewCount > 0 ? viewCount : 1;
					view.setYbnl(view.getYbnl() / count);
					view.setTysrl(view.getTysrl() / count);
					view.setZyzsjn(view.getZyzsjn() / count);
					view.setZhzyhnl(view.getZhzyhnl() / count);
					
					ret.getTeams().add(view);
				}
			}
		}

		return ret;
	}
	
	private String formatPercent(int value, int total) {
		return String.format("%.2f%%", value * 100.0 / total);
	}

	@Override
	public List<SudokuView> listSudokuBySize(int size) {

		validateDataset();

		TalentDataset data = TalentCache.my().get();
		if (data == null)
			return null;

		if (size <= 0 || size > 20)
			size = 15;

		List<SudokuView> ret = new ArrayList<SudokuView>();
		// 先提取部门
		if (data.getTeams().size() > 0) {
			int count = 0;

			for (NameTerm unit : data.getTeams()) {
				if (unit.getNodes() != null && unit.getNodes().size() > 0) {
					for (NameTerm depart : unit.getNodes()) {
						// 如果大于所需数，则退出
						if (count++ > size)
							break;

						SudokuView view = SudokuView.create(depart.getId(), depart.getText());
						ret.add(view);
					}
				}
				// 如果大于所需数，则退出
				if (count > size)
					break;
			}
		}
		// 处理人员并统计
		if (ret.size() > 0 && data.getDatas() != null && data.getDatas().size() > 0) {
			// 需要以下指标：
			// 综合专业化能力水平：=IF($AQ4>=7,"高",IF(AND($AQ4>=5,$AQ4<7),"中",IF($AQ4<5,"低")))
			// 上年度绩效等级
			//
			// =IF(AND(AR9=$AX$1,AU9=$AX$1),"9",IF(AND(AR9=$AX$1,AU9=$AY$1),"6",IF(AND(AR9=$AM$1,AU9=$AZ$1),"3",IF(AND(AR9=$AY$1,AU9=$AX$1),"8",IF(AND(AR9=$AY$1,AU9=$AY$1),"5",IF(AND(AR9=$AY$1,AU9=$AZ$1),"2",IF(AND(AR9=$AZ$1,AU9=$AX$1),"7",IF(AND(AR9=$AZ$1,AU9=$AY$1),"4",IF(AND(AR9=$AZ$1,AU9=$AZ$1),"1")))))))))
			for (SudokuView view : ret) {
				int count = 0;
				// 统计人员
				for (TalentCaution caution : data.getDatas()) {
					if (caution.getDepart().intValue() == view.getId().intValue()) {
						int index = 1;
						if (caution.getJgg() != null) {
							if (caution.getJgg() > 9)
								index = 9;
							else if (caution.getJgg() > 0)
								index = caution.getJgg();

						}
						SudokuCellView cell = view.getSudoku().get(index - 1);
						cell.incCount();
						cell.addName(caution.getName());

						count++;
					}
				}
				// 计算百分比和拼接评论
				if (count > 0) {
					int[] counts = new int[Utility.SUDOKU_CAPICITY];
					for (SudokuCellView cell : view.getSudoku()) {
						counts[cell.getCellIndex() - 1] += cell.getCount();
						cell.setPercent(formatPercent(cell.getCount(), count));
					}
					String str = "";
					boolean ok = ((counts[8] * 1.0 / count) >= 0.05)
							&& (((counts[6] + counts[7]) * 1.0 / count) >= 0.1);
					str = view.getName() + "员工整体专业能力表现相对" + (ok ? "较强，" : "一般，");

					str = str + formatPercent(counts[4] + counts[5] + counts[6] + counts[7] + counts[8], count)
							+ "以上的员工在专业化能力上表现相对较高；" + "A+档卓越员工数量为" + formatPercent(counts[8], count) + "( " + counts[8]
							+ " )，" + "A档优秀员工数量有" + formatPercent(counts[6] + counts[7], count) + "( "
							+ (counts[6] + counts[7]) + " )。";
					if (ok)
						str = str + "表现优秀的员工共数量充足，远高于管理通用要求";
					else
						str = str + "表现优秀的员工共数量较低，距离管理通用要求还有不少差距";
					str = str + "( 卓越员工不少于5%，优秀员工不少于10% )。";
					view.setRemark(str);

				}
			}
		}

		return ret;
	}

	@Override
	public List<SudokuView> listSudoku(Integer[] depart, Integer[] profs, Integer[] jobs) {

		if (depart == null || depart.length == 0)
			return null;

		validateDataset();

		TalentDataset data = TalentCache.my().get();
		if (data == null)
			return null;

		List<SudokuView> ret = new ArrayList<SudokuView>();

		for (Integer d : depart) {
			NameTerm nt = TalentCache.my().getTeam(d);
			if (nt != null) {
				SudokuView team = SudokuView.create(nt.getId(), nt.getText());
				ret.add(team);
			}
		}

		// 处理人员并统计
		//九宫格评价标准：
		//专业化能力水平值>=7 -> 能力定级：高
		//7>专业化能力水平值>=5 -> 能力定级：中
		//专业化能力水平值<5 -> 能力定级：低
		//能力定级  年度绩效等级 格子
		//	高		高		9
		//	高		中		6
		//	高		低		3
		//	中		高		8
		//	中		中		5
		//	中		低		2
		//	低		高		7
		//	低		中		4
		//	低		低		1
		if (ret.size() > 0 && data.getDatas() != null && data.getDatas().size() > 0) {
			for (SudokuView view : ret) {
				int count = 0;
				for (TalentCaution caution : data.getDatas()) {
					if (Utility.inArray(depart, caution.getDepart()) && Utility.inArray(profs, caution.getTechLevel())
							&& Utility.inArray(jobs, caution.getJob01())) {
						int index = 1;
						if (caution.getJgg() != null) {
							if (caution.getJgg() > 9)
								index = 9;
							else if (caution.getJgg() > 0)
								index = caution.getJgg();
							else
								index = 1;

						}
						SudokuCellView cell = view.getSudoku().get(index - 1);
						cell.incCount();
						cell.addName(caution.getName());

						count++;

					}
				}
				// 计算百分比和拼接评论
				if (count > 0) {
					int[] counts = new int[Utility.SUDOKU_CAPICITY];
					for (SudokuCellView cell : view.getSudoku()) {
						counts[cell.getCellIndex() - 1] += cell.getCount();
						cell.setPercent(formatPercent(cell.getCount(), count));
					}
					String str = "";
					boolean ok = ((counts[8] * 1.0 / count) >= 0.05)
							&& (((counts[6] + counts[7]) * 1.0 / count) >= 0.1);
					str = view.getName() + "员工整体专业能力表现相对" + (ok ? "较强，" : "一般，");

					str = str + formatPercent(counts[4] + counts[5] + counts[6] + counts[7] + counts[8], count)
							+ "以上的员工在专业化能力上表现相对较高；" + "A+档卓越员工数量为" + formatPercent(counts[8], count) + "( " + counts[8]
							+ " )," + "A档优秀员工数量有" + formatPercent(counts[6] + counts[7], count) + "( "
							+ (counts[6] + counts[7]) + " )。";
					if (ok)
						str = str + "表现优秀的员工数量充足，远高于管理通用要求";
					else
						str = str + "表现优秀的员工数量较低，距离管理通用要求还有不少差距";
					str = str + "( 卓越员工不少于5%，优秀员工不少于10% )。";
					view.setRemark(str);

				}
			}
		}

		return ret;
	}

	@Override
	public List<AbilityUserView> listTraficBySize(int size) {

		validateDataset();

		TalentDataset data = TalentCache.my().get();
		if (data == null)
			return null;

		List<AbilityUserView> ret = new ArrayList<AbilityUserView>();
		for (TalentCaution caution : data.getDatas()) {
			AbilityUserView cell = new AbilityUserView();

			cell.setNo(caution.getId());
			cell.setName(caution.getName());

			cell.setSxyy(caution.getSxyy());
			cell.setYylj(caution.getYylj());
			cell.setPdtl(caution.getPdtl());
			cell.setZlfx(caution.getZlfx());
			cell.setQjys(caution.getQjys());
			cell.setRwgl(caution.getRwgl());
			cell.setGtxt(caution.getGtxt());
			cell.setZdtr(caution.getZdtr());
			cell.setXxnl(caution.getXxnl());
			cell.setYtlj(caution.getYtlj());
			cell.setWzbd(caution.getWzbd());
			cell.setZhsrl(caution.getZhsrl());
			cell.setZyll(caution.getZyll());
			cell.setZyjn(caution.getZyjn());

			ret.add(cell);
		}

		return ret;
	}

	@Override
	public List<AbilityUserView> listTrafic(Integer[] depart, Integer[] profs, Integer[] jobs) {

		if (depart == null || depart.length == 0)
			return null;

		validateDataset();

		TalentDataset data = TalentCache.my().get();
		if (data == null)
			return null;

		List<AbilityUserView> ret = new ArrayList<AbilityUserView>();

		for (TalentCaution caution : data.getDatas()) {
			if (Utility.inArray(depart, caution.getDepart()) && Utility.inArray(profs, caution.getTechLevel())
					&& Utility.inArray(jobs, caution.getJob01())) {
				AbilityUserView cell = new AbilityUserView();

				cell.setNo(caution.getId());
				cell.setName(caution.getName());

				cell.setSxyy(caution.getSxyy());
				cell.setYylj(caution.getYylj());
				cell.setPdtl(caution.getPdtl());
				cell.setZlfx(caution.getZlfx());
				cell.setQjys(caution.getQjys());
				cell.setRwgl(caution.getRwgl());
				cell.setGtxt(caution.getGtxt());
				cell.setZdtr(caution.getZdtr());
				cell.setXxnl(caution.getXxnl());
				cell.setYtlj(caution.getYtlj());
				cell.setWzbd(caution.getWzbd());
				cell.setZhsrl(caution.getZhsrl());
				cell.setZyll(caution.getZyll());
				cell.setZyjn(caution.getZyjn());

				ret.add(cell);

			}
		}

		return ret;
	}

	@Override
	public AbilityUserView findUser(String no) {

		if (no == null || no.length() == 0)
			return null;

		validateDataset();

		TalentDataset data = TalentCache.my().get();
		if (data == null)
			return null;

		AbilityUserView cell = null;

		for (TalentCaution caution : data.getDatas()) {
			if(no.equals(caution.getId())){
				cell = new AbilityUserView();

				cell.setNo(caution.getId());
				cell.setName(caution.getName());
				cell.setJgg(caution.getJgg());
				cell.setNldj(caution.getNldj());
				cell.setSndjx(caution.getSndjx());

				break;

			}
		}

		return cell;
	}
	
	@Override
	public List<AgeYearsView> listAgeRatio(Integer[] depart, Integer[] profs, Integer[] jobs) {

		validateDataset();

		TalentDataset data = TalentCache.my().get();
		if (data == null)
			return null;

		List<AgeYearsView> ret = new ArrayList<AgeYearsView>();
		int thisyear = Utility.thisYear();
		//设置十年内
		for(int i=6; i>-4; i--){
			ret.add(0, AgeYearsView.create(i));
		}
		int[] counts = new int[10];
		int total =0;
		for(AgeYearsView v: ret) {
			total=0;
			Arrays.fill(counts, 0);
			for (TalentCaution caution : data.getDatas()) {
				if (Utility.inArray(depart, caution.getDepart()) && Utility.inArray(profs, caution.getTechLevel())
						&& Utility.inArray(jobs, caution.getJob01())) {
					total++;
					int yold =caution.getYearOld();
					if(yold<=0)
					   yold = Utility.ageLimit(caution.getBirthday());
					yold += v.getYear();
					
					if(yold>=55)
						counts[9]++;
					if(yold>=50&&yold<55)
						counts[8]++;
					if(yold>=50)
						counts[7]++;
					if(yold>=45&&yold<50)
						counts[6]++;
					if(yold>=40&&yold<44)
						counts[5]++;
					if(yold>=35&&yold<39)
						counts[4]++;
					if(yold>=35&&yold<50)
						counts[3]++;
					if(yold>=30&&yold<35)
						counts[2]++;
					if(yold<30)
						counts[1]++;
					if(yold<35)
						counts[0]++;
				}
			}
			for(int index=0; index<10;index++) {
				v.getAges().add(AgeRatioView.create(AgeLevel[index], counts[index], total));
			}
			v.setYear(v.getYear()+thisyear);
		}

		return ret;
	}
	
	private static String[] RC_TITLE = new String[] {
//			"国网级",
//			"省公司级",
//			"地市公司级",
//			"县公司级"
			"专家人才晋升趋势"
	};
	private void calcByRC(TalentCaution caution, Map<Integer, TrendView.TrendItem>[] mapArray) throws Exception {
		Map<Integer, TrendView.TrendItem> trendItemMap = mapArray[0];

		for (int i = 0; i < professionalNumTrendForecastYears; i++) {
			// 要计算的年月
			int calYear = DateUtil.date().year() + i;
			DateTime calDate = DateUtil.date().setField(DateField.YEAR, calYear);

			TrendView.TrendItem trendItem = trendItemMap.get(calYear);
			if (trendItem == null) {
				trendItem = new TrendView.TrendItem();
				trendItem.setYear(calYear);
				trendItemMap.put(calYear, trendItem);
			}
			trendItem.incCount();

			// 判定是否满足专家条件
			boolean isProf = judgingProfRule(caution, calDate);
			if (isProf) {
				// 满足专家条件, 专家数量+1
				trendItem.incTrendCount();
				// 满足条件的人才添加到返回值
				trendItem.addUser(caution);
			}
		}


//		String name = caution.getZjjb();
//		if (name == null || name.length() == 0)
//			return;
//
//		Education myEdu = Education.keyOf(caution.getHighEdu());
//
//		Map<Integer, TrendView.TrendItem> map = null;
//		int demoage = 0;
//		Education sedu = Education.QT;
//		if (name.indexOf("国网") >= 0) {
//			map = mapArray[0];
//			demoage = 45;
//			sedu=Education.SS;
//		} else if (name.indexOf("省公司") >= 0) {
//			map = mapArray[1];
//			demoage = 35;
//			sedu=Education.BK;
//		} else if (name.indexOf("地市公司") >= 0) {
//			map = mapArray[2];
//			demoage = 30;
//			sedu=Education.DZ;
//		} else if (name.indexOf("县公司") >= 0) {
//			map = mapArray[3];
//			demoage = 25;
//		}
//		if (map == null)
//			return;
//
//		int thisYear = Utility.thisYear();
//		for (int i = 1; i < 6; i++) {
//			TrendView.TrendItem sum = map.get(i);
//			if (sum == null) {
//				sum = new TrendView.TrendItem();
//				sum.setYear(thisYear + i);
//				map.put(i, sum);
//			}
//			sum.incCount();
//
//			if ((caution.getYearOld() + i >= demoage)&&myEdu.than(sedu)) {
//				sum.incTrendCount();
//			}
//		}

	}

	public boolean judgingProfRule(TalentCaution caution, DateTime calDate) throws Exception {
		// 筛选满足年限年以上
		Date eduDate = caution.getEduDate();
		// 返回true：前者+年份之后，大于等于后者.
		if (MyDateUtils.DateCompare(eduDate, calDate, 10)) {
			return false;
		}

		// 筛选年龄满足要求的
		Date birthday = caution.getBirthday();
		int age = MyDateUtils.getAgeByBirth(birthday);

		String gender = caution.getGender();
		if ("男".equals(gender)) {
			if (age > maleMaxProfessionAge) {
				return false;
			}
		} else if ("女".equals(gender)) {
			if (age > femaleMaxProfessionAge) {
				return false;
			}
		} else {
			throw new Exception("性别信息错误:" + caution.toString());
		}

		// 判断去年的绩效等级是否满足要求
		if (!Arrays.asList("01-A", "02-B").contains(caution.getSndjx())) {
			return false;
		}

		// 判断近几年的绩效积分
		if (caution.getRecentYearsPerformance() < minRecentYearsPerformance) {
			return false;
		}
		return true;


	}

	private static String[] ZC_TITLE = new String[] {
			"副高级升正高级趋势",
			"中级升副高级趋势",
			"助理级升中级趋势",
			"员级升助理级趋势"
	};
	private void calcByZC(TalentCaution caution, Map<Integer, TrendView.TrendItem>[] mapArray) {
		String techLevelName = caution.getTechLevelName();
		if(techLevelName==null || techLevelName.length()==0) {
			return;
		}

		Map<Integer, TrendView.TrendItem> trendItemMap = null;
		if(techLevelName.contains("副高级")) {
			trendItemMap = mapArray[0];
		}else if(techLevelName.contains("中级")) {
			trendItemMap = mapArray[1];
		}else if(techLevelName.contains("初级")) {
			trendItemMap = mapArray[2];
		}else if(techLevelName.contains("员级")) {
			trendItemMap = mapArray[3];
		}

		if(trendItemMap == null) {
			return;
		}

		for (int i = 0; i < professionalTitleNumTrendForecastYears; i++) {
			// 要计算的年月
			int calYear = DateUtil.date().year() + i;
			DateTime calDate = DateUtil.date().setField(DateField.YEAR, calYear);

			TrendView.TrendItem trendItem = trendItemMap.get(calYear);
			if (trendItem == null) {
				trendItem = new TrendView.TrendItem();
				trendItem.setYear(calYear);
				trendItemMap.put(calYear, trendItem);
			}
			trendItem.incCount();


			// 判定是否满足专家条件
			boolean satisfy = false;
			if(techLevelName.contains("副高级")) {
				satisfy = judgingHighRule(caution, calDate);
			}else if(techLevelName.contains("中级")) {
				satisfy = judgingDeputyHighRule(caution, calDate);
			}else if(techLevelName.contains("初级")) {
				satisfy = judgingMidRule(caution, calDate);
			}else if(techLevelName.contains("员级")) {
				satisfy = judgingInitialRule(caution, calDate);
			}

			if (satisfy) {
				// 满足条件, 数量+1
				trendItem.incTrendCount();
				trendItem.addUser(caution);
			}
		}

//		String name=caution.getTechLevelName();
//		if(name==null||name.length()==0)
//			return;
//		Map<Integer, TrendView.TrendItem> map = null;
//		int cmpAge = 0;
//		int cmpYears = 99;
//		if(name.indexOf("副高级")>=0) {
//			map = mapArray[0];
//			cmpAge = 35;
//			cmpYears = 5;
//		}else if(name.indexOf("中级")>=0) {
//			map = mapArray[1];
//			cmpAge = 30;
//			cmpYears = 3;
//		}else if(name.indexOf("初级")>=0) {
//			map = mapArray[2];
//			cmpAge = 25;
//			cmpYears = 2;
//		}else if(name.indexOf("员级")>=0) {
//			map = mapArray[3];
//			cmpAge = 23;
//			cmpYears = 0;
//		}
//		if(map==null)
//			return;
//
//		int myage = caution.getYearOld();
//		int myzcyear = Utility.ageLimit(caution.getTechLevelDate());
//		int thisYear = Utility.thisYear();
//		for(int i=1; i< 6; i++) {
//			TrendView.TrendItem sum = map.get(i);
//			if(sum==null) {
//				sum = new TrendView.TrendItem();
//				sum.setYear(thisYear+i);
//				map.put(i, sum);
//			}
//			sum.incCount();
//			if(myage>=cmpAge && myzcyear >= cmpYears) {
//				sum.incTrendCount();
//			}
//		}
	}

	/**
	 * 判断是否满足初级
	 */
	private boolean judgingInitialRule(TalentCaution caution, DateTime calDate) {
		return false;
	}

	/**
	 * 判断是否满足中级
	 */
	private boolean judgingMidRule(TalentCaution caution, DateTime calDate) {
		// 学历
		String highEdu = caution.getHighEdu();
		// 取得中级资格的时间
		Date techLevelDate = caution.getTechLevelDate();
		// 本专业工作年限
		Integer professionalYears = caution.getProfessionalYears();


		// 根据学历，判断助理级（初级）的工作年限是否满足要求
		Integer afterInitialMinYears = null;
		if (highEdu.equals(EducationType.college.getInfo())) {
			afterInitialMinYears = 4;
		} else if (highEdu.equals(EducationType.undergraduate.getInfo())) {
			afterInitialMinYears = 4;
		} else if (highEdu.equals(EducationType.master.getInfo())
				|| highEdu.equals(EducationType.partySchool.getInfo())
				|| highEdu.equals(EducationType.CPCPartySchool.getInfo())) {
			afterInitialMinYears = 2;
		} else {
			return false;
		}

		// 返回true：前者+年份之后，大于等于后者.
		if (MyDateUtils.DateCompare(techLevelDate, calDate, afterInitialMinYears)) {
			return false;
		}


		// 满足最小的本专业工作年限要求
		Integer minProfessionalYears = null;
		if (highEdu.equals(EducationType.college.getInfo())) {
			minProfessionalYears = 4;
		} else if (highEdu.equals(EducationType.undergraduate.getInfo())) {
			minProfessionalYears = 4;
		} else if (highEdu.equals(EducationType.master.getInfo())
				|| highEdu.equals(EducationType.partySchool.getInfo())
				|| highEdu.equals(EducationType.CPCPartySchool.getInfo())) {
			minProfessionalYears = 2;
		} else {
			return false;
		}

		if (professionalYears < minProfessionalYears) {
			return false;
		}
		return true;
	}

	/**
	 * 判断是否满足副高级
	 */
	private boolean judgingDeputyHighRule(TalentCaution caution, DateTime calDate) {
		// 学历
		String highEdu = caution.getHighEdu();
		// 取得中级资格的时间
		Date techLevelDate = caution.getTechLevelDate();
		// 本专业工作年限
		Integer professionalYears = caution.getProfessionalYears();


		// 根据学历，判断中级的工作年限是否满足要求
		Integer afterIntermediateMinYears = null;
		if (highEdu.equals(EducationType.college.getInfo())) {
			afterIntermediateMinYears = 10;
		} else if (highEdu.equals(EducationType.undergraduate.getInfo())) {
			afterIntermediateMinYears = 5;
		} else if (highEdu.equals(EducationType.master.getInfo())) {
			afterIntermediateMinYears = 5;
		} else if (highEdu.equals(EducationType.doctor.getInfo())) {
			afterIntermediateMinYears = 2;
		} else {
			return false;
		}

		// 返回true：前者+年份之后，大于等于后者.
		if (MyDateUtils.DateCompare(techLevelDate, calDate, afterIntermediateMinYears)) {
			return false;
		}


		// 满足最小的本专业工作年限要求
		Integer minProfessionalYears = null;
		if (highEdu.equals(EducationType.college.getInfo())) {
			minProfessionalYears = 7;
		} else if (highEdu.equals(EducationType.undergraduate.getInfo())
				|| highEdu.equals(EducationType.master.getInfo())
				|| highEdu.equals(EducationType.partySchool.getInfo())
				|| highEdu.equals(EducationType.CPCPartySchool.getInfo())) {
			minProfessionalYears = 5;
		} else if (highEdu.equals(EducationType.doctor.getInfo())) {
			minProfessionalYears = 2;
		} else {
			return false;
		}

		if (professionalYears < minProfessionalYears) {
			return false;
		}
		return true;
	}

	/**
	 * 判断是否满足高级
	 */
	private boolean judgingHighRule(TalentCaution caution, DateTime calDate) {
		// 具备大学本科及以上学历
		String highEdu = caution.getHighEdu();
		List<String> eduList = Arrays.asList(EducationType.undergraduate.getInfo(),
											  	EducationType.master.getInfo(),
												EducationType.partySchool.getInfo(),
												EducationType.CPCPartySchool.getInfo(),
												EducationType.doctor.getInfo());
		if (!eduList.contains(highEdu)) {
			return false;
		}


		// 取得资格时间超过一定年限
		Date techLevelDate = caution.getTechLevelDate();
		// 返回true：前者+年份之后，大于等于后者.
		if (MyDateUtils.DateCompare(techLevelDate, calDate, 5)) {
			return false;
		}


		// 满足最小的本专业工作年限要求
		Integer minProfessionalYears = null;
		if (highEdu.equals(EducationType.undergraduate.getInfo())) {
			minProfessionalYears = 15;
		} else if (highEdu.equals(EducationType.master.getInfo())
				|| highEdu.equals(EducationType.partySchool.getInfo())
				|| highEdu.equals(EducationType.CPCPartySchool.getInfo())) {
			minProfessionalYears = 12;
		} else if (highEdu.equals(EducationType.doctor.getInfo())) {
			minProfessionalYears = 7;
		} else {
			return false;
		}

		Integer professionalYears = caution.getProfessionalYears();
		// 返回true：前者+年份之后，大于等于后者.
		if (professionalYears < minProfessionalYears) {
			return false;
		}

		return true;
	}


	private static String[] JN_TITLE = new String[] {
			"技师级升高级技师级趋势",
			"高级工升技师级趋势",
			"中级工升高级工趋势",
			"初级工升中级工趋势"
	};
	private void calcByJN(TalentCaution caution, Map<Integer, TrendView.TrendItem>[] mapArray) {
		String skillLevelName = caution.getSkillLevelName();
		if(skillLevelName==null || skillLevelName.length()==0) {
			return;
		}

		Map<Integer, TrendView.TrendItem> trendItemMap = null;
		if(skillLevelName.equals("技师")) {
			trendItemMap = mapArray[0];
		}else if(skillLevelName.contains("高级工")) {
			trendItemMap = mapArray[1];
		}else if(skillLevelName.contains("中级工")) {
			trendItemMap = mapArray[2];
		}else if(skillLevelName.contains("初级工")) {
			trendItemMap = mapArray[3];
		}

		if(trendItemMap == null) {
			return;
		}

		for (int i = 0; i < professionalTitleNumTrendForecastYears; i++) {
			// 要计算的年月
			int calYear = DateUtil.date().year() + i;
			DateTime calDate = DateUtil.date().setField(DateField.YEAR, calYear);

			TrendView.TrendItem trendItem = trendItemMap.get(calYear);
			if (trendItem == null) {
				trendItem = new TrendView.TrendItem();
				trendItem.setYear(calYear);
				trendItemMap.put(calYear, trendItem);
			}
			trendItem.incCount();


			// 判定,根据不同的身份，是否满足晋级条件
			boolean satisfy = false;
			if(skillLevelName.equals("技师")) {
				satisfy = judgingGJJSRule(caution, calDate);
			}else if(skillLevelName.contains("高级工")) {
				satisfy = judgingJSRule(caution, calDate);
			}else if(skillLevelName.contains("中级工")) {
				satisfy = judgingGJGRule(caution, calDate);
			}else if(skillLevelName.contains("初级工")) {
				satisfy = judgingZJGRule(caution, calDate);
			}

			if (satisfy) {
				// 满足条件, 数量+1
				trendItem.incTrendCount();
				trendItem.addUser(caution);
			}
		}



//		String name=caution.getSkillLevelName();
//		if(name==null||name.length()==0)
//			return;
//
//		int cmpAge = 0;
//		int cmpYears = 99;
//		Map<Integer, TrendView.TrendItem> map = null;
//		if(name.indexOf("技师")>=0) {
//			map = mapArray[0];
//			cmpAge = 35;
//			cmpYears = 10;
//		}else if(name.indexOf("高级工")>=0) {
//			map = mapArray[1];
//			cmpAge = 30;
//			cmpYears = 5;
//		}else if(name.indexOf("中级工")>=0) {
//			map = mapArray[2];
//			cmpAge = 25;
//			cmpYears = 2;
//		}else if(name.indexOf("初级工")>=0) {
//			map = mapArray[3];
//			cmpAge = 20;
//			cmpYears = 0;
//		}
//		if(map==null)
//			return;
//
//		int thisYear = Utility.thisYear();
//		int myage = caution.getYearOld();
//		int myzcyear = Utility.ageLimit(caution.getSkillDate());
//		for(int i=1; i< 6; i++) {
//			TrendView.TrendItem sum = map.get(i);
//			if(sum==null) {
//				sum = new TrendView.TrendItem();
//				sum.setYear(thisYear+i);
//				map.put(i, sum);
//			}
//			sum.incCount();
//			if(myage>=cmpAge && myzcyear>=cmpYears) {
//				sum.incTrendCount();
//			}
//		}
	}

	/**
	 * 判断是否满足高级技师
	 */
	private boolean judgingGJJSRule(TalentCaution caution, DateTime calDate) {
		Date skillDate = caution.getSkillDate();
		// 返回true：前者+年份之后，大于等于后者.
		if (MyDateUtils.DateCompare(skillDate, calDate, 4)) {
			return false;
		}
		return true;
	}
	/**
	 * 判断是否满足技师
	 */
	private boolean judgingJSRule(TalentCaution caution, DateTime calDate) {
		Date skillDate = caution.getSkillDate();
		// 返回true：前者+年份之后，大于等于后者.
		if (MyDateUtils.DateCompare(skillDate, calDate, 4)) {
			return false;
		}
		return true;
	}
	/**
	 * 判断是否满足高级工
	 */
	private boolean judgingGJGRule(TalentCaution caution, DateTime calDate) {
		Date skillDate = caution.getSkillDate();
		// 返回true：前者+年份之后，大于等于后者.
		if (MyDateUtils.DateCompare(skillDate, calDate, 5)) {
			return false;
		}
		return true;
	}
	/**
	 * 判断是否满足中级工
	 */
	private boolean judgingZJGRule(TalentCaution caution, DateTime calDate) {
		Date skillDate = caution.getSkillDate();
		// 返回true：前者+年份之后，大于等于后者.
		if (MyDateUtils.DateCompare(skillDate, calDate, 1)) {
			return false;
		}
		return true;
	}


	@Override
	public TrendView listTrend(int type, Integer[] depart, Integer[] profs, Integer[] jobs) throws Exception {

		validateDataset();

		TalentDataset data = TalentCache.my().get();
		if (data == null)
			return null;

		TrendView ret = TrendView.create();
		Map<Integer, TrendView.TrendItem>[] items = null;
		String[] titles = null;
		switch(type) {
		case 0:
			titles = RC_TITLE;
			items=new Map[RC_TITLE.length];
			for(int index =0; index<RC_TITLE.length; index++)
				items[index] = new HashMap<>();
			break;
		case 1:
			titles = ZC_TITLE;
			items=new Map[ZC_TITLE.length];
			for(int index =0; index<ZC_TITLE.length; index++)
				items[index] = new HashMap<>();
			break;
		case 2:
			titles = JN_TITLE;
			items=new Map[JN_TITLE.length];
			for(int index =0; index<JN_TITLE.length; index++)
				items[index] = new HashMap<>();
			break;
		case 3:
			break;
		}


		Integer count = 0;
		for (TalentCaution caution : data.getDatas()) {
			if (Utility.inArray(depart, caution.getDepart()) && Utility.inArray(profs, caution.getTechLevel()) && Utility.inArray(jobs, caution.getJob01())) {
				count++;
				switch (type) {
					case 0:
						calcByRC(caution, items);
						break;
					case 1:
						calcByZC(caution, items);
						break;
					case 2:
						calcByJN(caution, items);
						break;
					case 3:
						TrendView.TrendUser usr = new TrendView.TrendUser();
						usr.setCareer(caution.getTechSerial());
						usr.setDepart(caution.getDepartName());
						usr.setId(caution.getId());
						usr.setJob(caution.getJob01Name());
						usr.setLongCareer(caution.getTechSerial());
						usr.setName(caution.getName());
						usr.setUnit(caution.getUnitName());
						usr.setYear(Utility.ageLimit(caution.getTechLevelDate()));
						usr.setCzsjzzy(caution.getCzsjzzy());
						usr.setCzsjzw(caution.getCzsjzw());
						usr.setScgwg3n(caution.getScgwg3n());
						usr.setYxgwg3n(caution.getYxgwg3n());
						usr.setRyzhly(caution.getRyzhly());
						usr.setRyzyly(caution.getRyzyly());
						usr.setRyjtlry(caution.getRyjtlry());
						usr.setRyzgry(caution.getRyzgry());
						usr.setRctchxtn(caution.getRctchxtn());
						usr.setRctchxtw(caution.getRctchxtw());
						ret.getUsers().add(usr);
				}
			}
		}

		if(titles!=null && items!=null && items.length>0) {
			for (int i=0; i < titles.length; i++) {
				TrendView.TrendSum sum = TrendView.TrendSum.create(i, titles[i]);
				sum.setItems(new ArrayList<>(items[i].values()));
				ret.getSums().add(sum);
			}
		}

		return ret;
	}

}
